#include "StdAfx.h"
#include "util.h"

std::string UTF8_to_ANSI (const char* szUTF8)
{
	if (szUTF8 == NULL)
		return "" ;
	
	int     nLen = ::MultiByteToWideChar (CP_UTF8, 0, szUTF8, -1, NULL, 0) ;
	WCHAR   * pWstr = new WCHAR[nLen+1] ;
	ZeroMemory (pWstr, sizeof(WCHAR) * (nLen+1)) ;
	::MultiByteToWideChar (CP_UTF8, 0, szUTF8, -1, pWstr, nLen) ;
	std::string     strAnsi (_bstr_t((wchar_t*)pWstr)) ;
	delete[] pWstr ;
	return strAnsi ;
}


std::string ANSI_to_UTF8 (const char* szAnsi)
{
	if (szAnsi == NULL)
		return "" ;
	
	_bstr_t   bstrTmp (szAnsi) ;
	int       nLen = ::WideCharToMultiByte (CP_UTF8, 0, (LPCWSTR)bstrTmp, -1, NULL, 0, NULL, NULL) ;
	char      * pUTF8 = new char[nLen+1] ;
	ZeroMemory (pUTF8, nLen + 1) ;
	::WideCharToMultiByte (CP_UTF8, 0, (LPCWSTR)bstrTmp, -1, pUTF8, nLen, NULL, NULL) ;
	std::string     strUTF (pUTF8) ;
	delete[] pUTF8 ;
	return strUTF ;
}

inline string trim_right (const string & s, const string & t /*= SPACES*/)
{ 
	string d (s); 
	string::size_type i (d.find_last_not_of (t));
	if (i == string::npos)
		return "";
	else
		return d.erase (d.find_last_not_of (t) + 1) ; 
}  // end of trim_right

inline string trim_left (const string & s, const string & t /*= SPACES*/) 
{ 
	string d (s); 
	return d.erase (0, s.find_first_not_of (t)) ; 
}  // end of trim_left

inline string trim (const string & s, const string & t /*= SPACES*/)
{ 
	string d (s); 
	return trim_left (trim_right (d, t), t) ; 
}  // end of trim

// returns a lower case version of the string 
string tolower (const string & s)
{
	string d (s);
	
	transform (d.begin (), d.end (), d.begin (), (int(*)(int)) tolower);
	return d;
}  // end of tolower

// returns an upper case version of the string 
string toupper (const string & s)
{
	string d (s);
	
	transform (d.begin (), d.end (), d.begin (), (int(*)(int)) toupper);
	return d;
}   // end of toupper


// returns a capitalized version of the string 
string tocapitals (const string & s)
{
	string d (s);
	
	transform (d.begin (), d.end (), d.begin (), fCapitals ());
	return d;
}  // end of tocapitals


// split a line into the first word, and rest-of-the-line
string GetWord (string & s, 
                const string delim /*= " "*/,
                const bool trim_spaces /*= true*/)
{
    
	// find delimiter  
	string::size_type i (s.find (delim));
	
	// split into before and after delimiter
	string w (s.substr (0, i));
	
	// if no delimiter, remainder is empty
	if (i == string::npos)
		s.erase ();
	else
		// erase up to the delimiter
		s.erase (0, i + delim.size ());
	
	// trim spaces if required
	if (trim_spaces)
    {
		w = trim (w);
		s = trim (s);
    }
	
	// return first word in line
	return w;
	
} // end of GetWord	

// To be symmetric, we assume an empty string (after trimming spaces)
// will give an empty vector.
// However, a non-empty string (with no delimiter) will give one item
// After that, you get an item per delimiter, plus 1.
// eg.  ""      => empty
//      "a"     => 1 item
//      "a,b"   => 2 items
//      "a,b,"  => 3 items (last one empty)

void StringToVector (const string s, 
                     vector<string> & v,
                     const string delim /*= " "*/, 
                     const bool trim_spaces /*= true*/)
{
	
	// start with initial string, trimmed of leading/trailing spaces if required
	string s1 (trim_spaces ? trim (s) : s);
	
	v.clear (); // ensure vector empty
	
	// no string? no elements
	if (s1.empty ())
		return;
	
	// add to vector while we have a delimiter
	while (!s1.empty () && s1.find (delim) != string::npos)
		v.push_back (GetWord (s1, delim, trim_spaces));
	
	// add final element
	v.push_back (s1);
} // end of StringToVector 

// Takes a vector of strings and converts it to a string 
// like "apples,peaches,pears" 
// Should be symmetric with StringToVector (excepting any spaces that might have
//  been trimmed).

string VectorToString (const vector<string> & v, 
                       const string delim /*= " "*/)
{
	// vector empty gives empty string
	if (v.empty ())
		return "";
	
	// for copying results into
	ostringstream os;
	
	// copy all but last one, with delimiter after each one
	copy (v.begin (), v.end () - 1, 
        ostream_iterator<string> (os, delim.c_str ()));
	
	// return string with final element appended
	return os.str () + *(v.end () - 1);
	
} 